﻿// -----------------------------------------------------------------------
// <copyright file="RegistryItem.cs" company="">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

using System.ComponentModel;

namespace VSTweaker
{
    using System;
    using Microsoft.Win32;

    public class RegistryItem : IDisposable, INotifyPropertyChanged
    {
        private RegistryKey _hklmKey;
        private RegistryKey _hkcuKey;

        public string Description {get;set;}

        public RegistryItem(RegistryKey hKey, string description)
        {
            using (var hklm = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32))
            {
                string parentName = hKey.Name.Replace("_Config", "").Replace("HKEY_CURRENT_USER\\", String.Empty);

                _hklmKey =
                    hklm.OpenSubKey(parentName);
            }

            _hkcuKey = hKey;
            Description = description;
        }

        public bool Enabled
        {
            get
            {
                var lastSlash = _hkcuKey.Name.LastIndexOf("\\") + 1;
                var packageGuid = _hkcuKey.Name.Substring(lastSlash, _hkcuKey.Name.Length - lastSlash);

                Guid guid;
                return Guid.TryParse(packageGuid, out guid);
            }
            set
            {
                if (value)
                {
                    if (!Enabled)
                    {
                        Enable();    
                    }
                }
                else
                {
                    if (Enabled)
                    {
                        Disable();    
                    }
                }

                OnPropertyChaned("Enabled");
            }
        }

        public void Toggle()
        {
            if (Enabled)
            {
                Disable();
            }
            else
            {
                Enable();
            }
        }

        public bool Enable()
        {
            if (Enabled)
            {
                throw new Exception("The registry item is already enabled!");
            }

            int lastSlash = 0;
            string parentKeyString = String.Empty;
            string packageGuidWithQuestion = String.Empty;
            if (_hklmKey != null)
            {
                lastSlash = _hklmKey.Name.LastIndexOf("\\");
                parentKeyString = _hklmKey.Name.Substring(0, lastSlash).Replace("HKEY_LOCAL_MACHINE\\", String.Empty);
                packageGuidWithQuestion = _hklmKey.Name.Substring(lastSlash + 1,
                                                                      _hklmKey.Name.Length - lastSlash - 1);

                var hklm = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32);

                using (var parentKey = hklm.OpenSubKey(parentKeyString, true))
                {
                    if (parentKey == null) return false;

                    _hklmKey.Close();
                    _hklmKey.Dispose();

                    var packageGuid = packageGuidWithQuestion.Substring(0, packageGuidWithQuestion.Length - 1);

                    if (!parentKey.RenameSubKey(packageGuidWithQuestion, packageGuid))
                    {
                        return false;
                    }

                    _hklmKey = parentKey.OpenSubKey(packageGuid);
                }
            }

            lastSlash = _hkcuKey.Name.LastIndexOf("\\");
            parentKeyString = _hkcuKey.Name.Substring(0, lastSlash).Replace("HKEY_CURRENT_USER\\", String.Empty);
            packageGuidWithQuestion = _hkcuKey.Name.Substring(lastSlash + 1, _hkcuKey.Name.Length - lastSlash - 1);

            var hkcu = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64);

            using (var parentKey = hkcu.OpenSubKey(parentKeyString, true))
            {
                if (parentKey == null) return false;

                _hkcuKey.Close();
                _hkcuKey.Dispose();

                var packageGuid = packageGuidWithQuestion.Substring(0, packageGuidWithQuestion.Length - 1);

                if (!parentKey.RenameSubKey(packageGuidWithQuestion, packageGuid))
                {
                    return false;
                }

                _hkcuKey = parentKey.OpenSubKey(packageGuid);

                return _hkcuKey != null;
            }
            


        }

        public bool Disable()
        {
            if (!Enabled)
            {
                throw new Exception("The registry item is already disabled!");
            }

            int lastSlash = 0;
            string parentKeyString = String.Empty;
            string packageGuidWithQuestion = String.Empty;
            if (_hklmKey != null)
            {
                lastSlash = _hklmKey.Name.LastIndexOf("\\");
                parentKeyString = _hklmKey.Name.Substring(0, lastSlash).Replace("HKEY_LOCAL_MACHINE\\", String.Empty);

                var hklm = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32);

                using (var parentKey = hklm.OpenSubKey(parentKeyString, true))
                {
                    if (parentKey == null) return false;

                    var packageGuid = _hklmKey.GetKeyName();

                    _hklmKey.Close();
                    _hklmKey.Dispose();

                    if (!parentKey.RenameSubKey(packageGuid, packageGuid + "?"))
                    {
                        return false;
                    }

                    _hklmKey = parentKey.OpenSubKey(packageGuid + "?");
                }
            }

            lastSlash = _hkcuKey.Name.LastIndexOf("\\");
            parentKeyString = _hkcuKey.Name.Substring(0, lastSlash).Replace("HKEY_CURRENT_USER\\", String.Empty);
            var hkcu = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64);

            using (var parentKey = hkcu.OpenSubKey(parentKeyString, true))
            {
                if (parentKey == null) return false;
                var packageGuid = _hkcuKey.GetKeyName();

                _hkcuKey.Close();
                _hkcuKey.Dispose();

                if (!parentKey.RenameSubKey(packageGuid, packageGuid + "?"))
                {
                    return false;
                }

                _hkcuKey = parentKey.OpenSubKey(packageGuid + "?");

                return _hkcuKey != null;
            }
        }



        public override string ToString()
        {
            return Description;
        }

        public override bool Equals(object obj)
        {
            return Description.Equals(obj);
        }

        public override int GetHashCode()
        {
            return Description.GetHashCode();
        }

        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        /// <filterpriority>2</filterpriority>
        public void Dispose()
        {
            if (_hklmKey != null)
            {
                _hklmKey.Dispose();
            }

            if (_hkcuKey != null)
            {
                _hkcuKey.Dispose();
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChaned(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}
